﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using MSH.Common.DAO.Results;
using System.Runtime.Serialization.Json;
using System.Timers;
using System.Threading;
using System.Globalization;

namespace ServerPerformanceTest
{
    public class Coordinate
    {
        public double lat, lon = 0;

        public Coordinate(double lat, double lon)
        {
            this.lat = lat;
            this.lon = lon;           
        }
    }

    public class MSHTest
    { 
        public static object LockObject = new Object();
        public static Int32 ThreadCounter = 0;

        //Configuration constants
        public static String ServiceURL = "http://83.85.182.120:1337";
        
        public static long TimerIntervalRefresh = 30000;
        public static long TimerIntervalLocation = 30000;
        public static String RangeFriendsNearby = "1000";

        public static Coordinate[] Coordinates = new Coordinate[] { new Coordinate(52.10319, 5.10604),
            new Coordinate(52.10940, 5.02095), new Coordinate(40.71435, -74.00597),new Coordinate(52.091195, 5.241208),
            new Coordinate(52.3734167, 4.8980556),new Coordinate(52.1109048, 5.1025691),new Coordinate(36.560139, 32.002121),
            new Coordinate(35.240117, 24.8092691),new Coordinate(36.8913183, 27.2834752),new Coordinate(37.035339, 27.43029)
        };

        private String username = null;
        private String password = "e358efa489f58062f10dd7316b65649e";
        private String sessionToken = null;

        private System.Timers.Timer locationTimer;
        private System.Timers.Timer refreshTimer;


        public MSHTest()
        {
            lock(LockObject)
            {
                ThreadCounter++;
                username = "Thread"+ThreadCounter;
            }
        }

        public void Run()
        {
            Console.WriteLine(username+": Run()");

            try
            {
                if (!Login())
                    throw new Exception("Login failed.");

                InitializeTimers();


            }
            catch(Exception e)
            {
                Console.WriteLine(username + ": exception: "+ e);
                return;
            }

          
        }

        private T GetWebserviceResponse<T>(String url)
        {

            WebRequest request = WebRequest.Create(ServiceURL + url);
            request.Method = "GET";

            using (WebResponse response = request.GetResponse())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
                T resultObject = (T)ser.ReadObject(response.GetResponseStream());
                response.Close();
                return resultObject;
            }
        }

        private bool Login()
        {

            LoginResult result = GetWebserviceResponse<LoginResult>(String.Format("/Login/{0}/{1}/Other", username, password));

            if (result == null || result.Result != MSH.Common.Classes.LoginResultEnum.Success)
                return false;
            else
            {
                sessionToken = result.Token;
                return true;
            }
        }

        private void GetChatmessages()
        {
            GetChatMessagesResult result = GetWebserviceResponse<GetChatMessagesResult>(String.Format("/GetChatMessages/{0}",sessionToken));
        }

        private void GetFriendList()
        {
            GetFriendListResult result = GetWebserviceResponse<GetFriendListResult>(String.Format("/GetFriendList/{0}", sessionToken));
        }

        private void GetPeopleNearby()
        {
            GetPeopleNearbyResult result = GetWebserviceResponse<GetPeopleNearbyResult>(String.Format("/GetPeopleNearby/{0}/{1}", sessionToken, RangeFriendsNearby));
        }

        private void GetFriendInvitations()
        {
            GetFriendInvitationsResult result = GetWebserviceResponse<GetFriendInvitationsResult>(String.Format("/GetFriendInvitations/{0}", sessionToken));
        }

        private void GetSocialNetworkAccounts()
        {
            GetSocialNetworkAccountsResult result = GetWebserviceResponse<GetSocialNetworkAccountsResult>(String.Format("/GetSocialNetworkAccounts/{0}/True", sessionToken));
        }

        private void UpdateUserLocation()
        {
            Random rd = new Random();
            Coordinate coord = Coordinates[rd.Next(0, Coordinates.Length - 1)];
            NumberFormatInfo numberFormatter = new CultureInfo("nl-NL").NumberFormat;
            String Longitude = Convert.ToString(coord.lon, numberFormatter);
            String Latitude = Convert.ToString(coord.lat, numberFormatter);
            UpdateLocationResult result = GetWebserviceResponse<UpdateLocationResult>(String.Format("/UpdateLocation/{0}/{1}/{2}", sessionToken, Latitude, Longitude));
        }

        private void InitializeTimers()
        {
            refreshTimer = new System.Timers.Timer(TimerIntervalRefresh);
            refreshTimer.Elapsed += new ElapsedEventHandler(OnTimerRefresh);
            refreshTimer.Enabled = true;
            OnTimerRefresh(null, null);
            locationTimer = new System.Timers.Timer(TimerIntervalLocation);
            locationTimer.Elapsed += new ElapsedEventHandler(OnTimerLocation);
            locationTimer.Enabled = true;
            OnTimerLocation(null, null);
        }

        private void OnTimerRefresh(object source, ElapsedEventArgs e)
        {
            //Wacht een random tijd
            Random rd = new Random();
            Thread.Sleep(rd.Next(0, 5000));

            GetChatmessages();
            GetFriendList();
            GetPeopleNearby();
            GetFriendInvitations();
            GetSocialNetworkAccounts();
        }

        private void OnTimerLocation(object source, ElapsedEventArgs e)
        {
            UpdateUserLocation();
        }

    }
}
